weston: fix crash on RaspberryPi 3 with VC4 DRM driver
authorDaniel Golle <[email protected]>
Fri, 18 Jul 2025 17:05:38 +0000 (18:05 +0100)
committerDaniel Golle <[email protected]>
Sat, 19 Jul 2025 15:56:01 +0000 (16:56 +0100)
See issue:
https://gitlab.freedesktop.org/wayland/weston/-/issues/1024

Patches imported are:
https://gitlab.freedesktop.org/wayland/weston/-/merge_requests/1621

Hopefully they will be part of an 14.0.3 release.

Signed-off-by: Daniel Golle <[email protected]>
frameworks/weston/Makefile
frameworks/weston/patches/001-drm-try-other-planes-that-may-support-fences.patch [new file with mode: 0644]
frameworks/weston/patches/002-drm-fix-a-few-dma-buf-feedback-failure-reasons.patch [new file with mode: 0644]
frameworks/weston/patches/003-drm-fix-issue-with-enum-being-wrongly-used.patch [new file with mode: 0644]
frameworks/weston/patches/004-drm-avoid-dma-buf-feedback-endless-loop.patch [new file with mode: 0644]

index 3ae7c618f1cb0f4717ffeb04d509b6af28790bf1..03f20f1f22338f73fa34fdda6629b6aaa423ec73 100644 (file)
@@ -1,7 +1,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=weston
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_VERSION:=14.0.2
 PKG_MAJOR_VERSION:=$(firstword $(subst .,$(space),$(PKG_VERSION)))
diff --git a/frameworks/weston/patches/001-drm-try-other-planes-that-may-support-fences.patch b/frameworks/weston/patches/001-drm-try-other-planes-that-may-support-fences.patch
new file mode 100644 (file)
index 0000000..aabc74a
--- /dev/null
@@ -0,0 +1,25 @@
+From 8f1a08991789cde7652ff4ccb9a9a46abe18d74e Mon Sep 17 00:00:00 2001
+From: Leandro Ribeiro <[email protected]>
+Date: Mon, 23 Sep 2024 17:06:31 -0300
+Subject: [PATCH 1/4] drm: try other planes that may support fences
+
+Do not skip all the planes if a single one of them do not support
+fences. The other may do.
+
+Signed-off-by: Leandro Ribeiro <[email protected]>
+(cherry picked from commit b347af2ce0fca3c7616d5a4d6500ca8770ad3252)
+---
+ libweston/backend-drm/state-propose.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/libweston/backend-drm/state-propose.c
++++ b/libweston/backend-drm/state-propose.c
+@@ -595,7 +595,7 @@ drm_output_find_plane_for_view(struct dr
+                   plane->props[WDRM_PLANE_IN_FENCE_FD].prop_id == 0) {
+                       drm_debug(b, "\t\t\t\t[%s] not placing view %p on %s: "
+                                 "no in-fence support\n", p_name, ev, p_name);
+-                      return NULL;
++                      continue;
+               }
+               if (!b->has_underlay && mm_has_underlay) {
diff --git a/frameworks/weston/patches/002-drm-fix-a-few-dma-buf-feedback-failure-reasons.patch b/frameworks/weston/patches/002-drm-fix-a-few-dma-buf-feedback-failure-reasons.patch
new file mode 100644 (file)
index 0000000..3ae82ef
--- /dev/null
@@ -0,0 +1,72 @@
+From 6445af1eade0fcdcc522cd9c1d45d840b87190bb Mon Sep 17 00:00:00 2001
+From: Leandro Ribeiro <[email protected]>
+Date: Tue, 24 Sep 2024 10:08:05 -0300
+Subject: [PATCH 2/4] drm: fix a few dma-buf feedback failure reasons
+
+There are a few points in the code where we are wrongly using
+FAILURE_REASONS_ADD_FB_FAILED, probably because we didn't have so many
+"failure reasons" previously. This update such cases to use enum's that
+make sense.
+
+Signed-off-by: Leandro Ribeiro <[email protected]>
+(cherry picked from commit 3210cec531702177d24c42bb56486124eda00f19)
+---
+ libweston/backend-drm/drm-internal.h  | 11 ++++++-----
+ libweston/backend-drm/state-propose.c |  8 ++++----
+ 2 files changed, 10 insertions(+), 9 deletions(-)
+
+--- a/libweston/backend-drm/drm-internal.h
++++ b/libweston/backend-drm/drm-internal.h
+@@ -163,11 +163,12 @@ enum try_view_on_plane_failure_reasons {
+       FAILURE_REASONS_INADEQUATE_CONTENT_PROTECTION = 1 << 6,
+       FAILURE_REASONS_INCOMPATIBLE_TRANSFORM = 1 << 7,
+       FAILURE_REASONS_NO_BUFFER = 1 << 8,
+-      FAILURE_REASONS_BUFFER_TYPE = 1 << 9,
+-      FAILURE_REASONS_GLOBAL_ALPHA = 1 << 10,
+-      FAILURE_REASONS_NO_GBM = 1 << 11,
+-      FAILURE_REASONS_GBM_BO_IMPORT_FAILED = 1 << 12,
+-      FAILURE_REASONS_GBM_BO_GET_HANDLE_FAILED = 1 << 13,
++      FAILURE_REASONS_BUFFER_TOO_BIG = 1 << 9,
++      FAILURE_REASONS_BUFFER_TYPE = 1 << 10,
++      FAILURE_REASONS_GLOBAL_ALPHA = 1 << 11,
++      FAILURE_REASONS_NO_GBM = 1 << 12,
++      FAILURE_REASONS_GBM_BO_IMPORT_FAILED = 1 << 13,
++      FAILURE_REASONS_GBM_BO_GET_HANDLE_FAILED = 1 << 14,
+ };
+ /**
+--- a/libweston/backend-drm/state-propose.c
++++ b/libweston/backend-drm/state-propose.c
+@@ -419,7 +419,7 @@ drm_output_find_plane_for_view(struct dr
+       /* check view for valid buffer, doesn't make sense to even try */
+       if (!weston_view_has_valid_buffer(ev)) {
+               pnode->try_view_on_plane_failure_reasons |=
+-                      FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE;
++                      FAILURE_REASONS_NO_BUFFER;
+               return NULL;
+       }
+@@ -431,12 +431,12 @@ drm_output_find_plane_for_view(struct dr
+       buffer = ev->surface->buffer_ref.buffer;
+       if (buffer->type == WESTON_BUFFER_SOLID) {
+               pnode->try_view_on_plane_failure_reasons |=
+-                      FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE;
++                      FAILURE_REASONS_BUFFER_TYPE;
+               return NULL;
+       } else if (buffer->type == WESTON_BUFFER_SHM) {
+               if (!output->cursor_plane || device->cursors_are_broken) {
+                       pnode->try_view_on_plane_failure_reasons |=
+-                              FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE;
++                              FAILURE_REASONS_BUFFER_TYPE;
+                       return NULL;
+               }
+@@ -457,7 +457,7 @@ drm_output_find_plane_for_view(struct dr
+                                    "(buffer (%dx%d) too large for cursor plane)\n",
+                                    ev, buffer->width, buffer->height);
+                       pnode->try_view_on_plane_failure_reasons |=
+-                              FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE;
++                              FAILURE_REASONS_BUFFER_TOO_BIG;
+                       return NULL;
+               }
diff --git a/frameworks/weston/patches/003-drm-fix-issue-with-enum-being-wrongly-used.patch b/frameworks/weston/patches/003-drm-fix-issue-with-enum-being-wrongly-used.patch
new file mode 100644 (file)
index 0000000..7994eb8
--- /dev/null
@@ -0,0 +1,29 @@
+From 0b5c47edcaf0e197f601fbf82bb3c52da8d93c87 Mon Sep 17 00:00:00 2001
+From: Leandro Ribeiro <[email protected]>
+Date: Tue, 24 Sep 2024 10:08:51 -0300
+Subject: [PATCH 3/4] drm: fix issue with enum being wrongly used
+
+FAILURE_REASONS_ADD_FB_FAILED is defined as (1 << 3), so when we are
+accumulating "failure reasons" in a variable we don't need to do the bit
+shift again.
+
+This results in an issue, because (1 << FAILURE_REASONS_ADD_FB_FAILED)
+results in (1 << (1 << 3)) == (1 << 8).
+
+Signed-off-by: Leandro Ribeiro <[email protected]>
+(cherry picked from commit 8b83bb5cebe64b672e978dc3423afe97d6178b7e)
+---
+ libweston/backend-drm/fb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/libweston/backend-drm/fb.c
++++ b/libweston/backend-drm/fb.c
+@@ -742,7 +742,7 @@ drm_fb_get_from_paint_node(struct drm_ou
+               fb = drm_fb_get_from_bo(bo, device, is_opaque, BUFFER_CLIENT);
+               if (!fb) {
+                       pnode->try_view_on_plane_failure_reasons |=
+-                              (1 << FAILURE_REASONS_ADD_FB_FAILED);
++                              FAILURE_REASONS_ADD_FB_FAILED;
+                       gbm_bo_destroy(bo);
+                       goto unsuitable;
+               }
diff --git a/frameworks/weston/patches/004-drm-avoid-dma-buf-feedback-endless-loop.patch b/frameworks/weston/patches/004-drm-avoid-dma-buf-feedback-endless-loop.patch
new file mode 100644 (file)
index 0000000..4bd1851
--- /dev/null
@@ -0,0 +1,172 @@
+From 1a9149cc062ac744ab190c8b2dc34102ca8a0adc Mon Sep 17 00:00:00 2001
+From: Leandro Ribeiro <[email protected]>
+Date: Tue, 24 Sep 2024 11:23:50 -0300
+Subject: [PATCH 4/4] drm: avoid dma-buf feedback endless loop
+
+Currently we have the following situation: we add a scanout tranche
+because if the client re-allocates with another format/modifier, the
+chances of being placed in a DRM/KMS plane is higher.
+
+But then we run out of overlay planes. So we remove the scanout tranche,
+because the format/modifier available in the renderer tranche are
+optimal for rendering.
+
+Now Weston detects again that the format/modifier is what may be
+avoiding the view being place in a plane, re-adding the scanout tranche.
+And we have an endless loop.
+
+To avoid this, let's accumulate the reasons why placing the view in a
+place failed. So if we detect that we don't have planes available, no
+matter the format/modifier, we won't add the scanout tranche.
+
+Signed-off-by: Leandro Ribeiro <[email protected]>
+(cherry picked from commit d3ead778dea9bde77d318292b8870e746cad5c3d)
+---
+ libweston/backend-drm/state-propose.c | 55 +++++++++++----------------
+ 1 file changed, 23 insertions(+), 32 deletions(-)
+
+--- a/libweston/backend-drm/state-propose.c
++++ b/libweston/backend-drm/state-propose.c
+@@ -413,9 +413,15 @@ drm_output_find_plane_for_view(struct dr
+       bool view_matches_entire_output, scanout_has_view_assigned;
+       uint32_t possible_plane_mask = 0;
++      bool any_candidate_picked = false;
+       pnode->try_view_on_plane_failure_reasons = FAILURE_REASONS_NONE;
++      /* filter out non-cursor views in renderer-only mode */
++      if (mode == DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY &&
++          ev->layer_link.layer != &b->compositor->cursor_layer)
++                      return NULL;
++
+       /* check view for valid buffer, doesn't make sense to even try */
+       if (!weston_view_has_valid_buffer(ev)) {
+               pnode->try_view_on_plane_failure_reasons |=
+@@ -423,32 +429,23 @@ drm_output_find_plane_for_view(struct dr
+               return NULL;
+       }
+-      /* filter out non-cursor views in renderer-only mode */
+-      if (mode == DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY &&
+-          ev->layer_link.layer != &b->compositor->cursor_layer)
+-                      return NULL;
+-
+       buffer = ev->surface->buffer_ref.buffer;
+       if (buffer->type == WESTON_BUFFER_SOLID) {
+               pnode->try_view_on_plane_failure_reasons |=
+                       FAILURE_REASONS_BUFFER_TYPE;
+-              return NULL;
+       } else if (buffer->type == WESTON_BUFFER_SHM) {
+-              if (!output->cursor_plane || device->cursors_are_broken) {
++              if (!output->cursor_plane || device->cursors_are_broken)
+                       pnode->try_view_on_plane_failure_reasons |=
+                               FAILURE_REASONS_BUFFER_TYPE;
+-                      return NULL;
+-              }
+-              /* Even though this is a SHM buffer, pixel_format stores the
+-               * format code as DRM FourCC */
++              /* Even though this is a SHM buffer, pixel_format stores
++               * the format code as DRM FourCC */
+               if (buffer->pixel_format->format != DRM_FORMAT_ARGB8888) {
+                       drm_debug(b, "\t\t\t\t[view] not placing view %p on "
+-                                   "plane; SHM buffers must be ARGB8888 for "
++                                   "plane; SHM buffers must be ARGB8888 for "
+                                    "cursor view\n", ev);
+                       pnode->try_view_on_plane_failure_reasons |=
+                               FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE;
+-                      return NULL;
+               }
+               if (buffer->width > device->cursor_width ||
+@@ -458,10 +455,10 @@ drm_output_find_plane_for_view(struct dr
+                                    ev, buffer->width, buffer->height);
+                       pnode->try_view_on_plane_failure_reasons |=
+                               FAILURE_REASONS_BUFFER_TOO_BIG;
+-                      return NULL;
+               }
+-              possible_plane_mask = (1 << output->cursor_plane->plane_idx);
++              if (pnode->try_view_on_plane_failure_reasons == FAILURE_REASONS_NONE)
++                      possible_plane_mask = (1 << output->cursor_plane->plane_idx);
+       } else {
+               if (mode == DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY) {
+                       drm_debug(b, "\t\t\t\t[view] not assigning view %p "
+@@ -477,20 +474,16 @@ drm_output_find_plane_for_view(struct dr
+                               possible_plane_mask |= 1 << plane->plane_idx;
+               }
+-              if (!possible_plane_mask) {
++              if (!possible_plane_mask)
+                       pnode->try_view_on_plane_failure_reasons |=
+                               FAILURE_REASONS_INCOMPATIBLE_TRANSFORM;
+-                      return NULL;
+-              }
+               fb = drm_fb_get_from_paint_node(state, pnode);
+-              if (!fb) {
++              if (fb)
++                      possible_plane_mask &= fb->plane_mask;
++              else
+                       drm_debug(b, "\t\t\t[view] couldn't get FB for view: 0x%lx\n",
+-                                (unsigned long) pnode->try_view_on_plane_failure_reasons);
+-                      return NULL;
+-              }
+-
+-              possible_plane_mask &= fb->plane_mask;
++                                   (unsigned long) pnode->try_view_on_plane_failure_reasons);
+       }
+       view_matches_entire_output =
+@@ -521,7 +514,6 @@ drm_output_find_plane_for_view(struct dr
+                       assert(plane == output->cursor_plane);
+                       break;
+               case WDRM_PLANE_TYPE_PRIMARY:
+-                      assert(fb);
+                       if (plane != output->scanout_plane)
+                               continue;
+                       if (mode != DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY)
+@@ -530,7 +522,6 @@ drm_output_find_plane_for_view(struct dr
+                               continue;
+                       break;
+               case WDRM_PLANE_TYPE_OVERLAY:
+-                      assert(fb);
+                       assert(mode != DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY);
+                       /* if the view covers the whole output, put it in the
+                        * scanout plane, not overlay */
+@@ -613,6 +604,7 @@ drm_output_find_plane_for_view(struct dr
+               else
+                       zpos = MIN(current_lowest_zpos - 1, plane->zpos_max);
++              any_candidate_picked = true;
+               drm_debug(b, "\t\t\t\t[plane] plane %d picked "
+                            "from candidate list, type: %s\n",
+                            plane->plane_id, p_name);
+@@ -620,9 +612,10 @@ drm_output_find_plane_for_view(struct dr
+               if (plane->type == WDRM_PLANE_TYPE_CURSOR) {
+                       ps = drm_output_prepare_cursor_paint_node(state, pnode, zpos);
+               } else {
+-                      ps = drm_output_try_paint_node_on_plane(plane, state,
+-                                                              pnode, mode,
+-                                                              fb, zpos);
++                      if (fb)
++                              ps = drm_output_try_paint_node_on_plane(plane, state,
++                                                                      pnode, mode,
++                                                                      fb, zpos);
+               }
+               if (ps) {
+@@ -641,11 +634,9 @@ drm_output_find_plane_for_view(struct dr
+                       FAILURE_REASONS_PLANES_REJECTED;
+       }
+-      if (!ps &&
+-          pnode->try_view_on_plane_failure_reasons == FAILURE_REASONS_NONE) {
++      if (!any_candidate_picked)
+               pnode->try_view_on_plane_failure_reasons |=
+                       FAILURE_REASONS_NO_PLANES_AVAILABLE;
+-      }
+       /* if we have a plane state, it has its own ref to the fb; if not then
+        * we drop ours here */